package biz

import (
	"context"
	"review-service/api/review/v1"
	"review-service/dal/model"
	"review-service/pkg/snowflake"
	"strings"
	"time"

	"github.com/go-kratos/kratos/v2/log"
)

// ReviewRepo is a Review repo.
type ReviewRepo interface {
	Save(context.Context, *model.ReviewInfo) (*model.ReviewInfo, error)
	GetReviewByOrderID(context.Context, int64) ([]*model.ReviewInfo, error)
	AuditReview(context.Context, *model.ReviewInfo) (*model.ReviewInfo, error)
	FindByReviewID(context.Context, int64) (*model.ReviewInfo, error)
	SaveReply(context.Context, *model.ReviewReplyInfo) (*model.ReviewReplyInfo, error)
	AppealReview(context.Context, *model.ReviewAppealInfo) (*model.ReviewAppealInfo, error)
	AuditAppeal(ctx context.Context, r *model.ReviewAppealInfo) error
	ListByHello(context.Context, string) ([]*model.ReviewInfo, error)
	ListAll(context.Context) ([]*model.ReviewInfo, error)
	ListReviewByStoreID(context.Context, int64, int32, int32) ([]*MyReviewInfo, error)
}

// ReviewUsecase is a Review usecase.
type ReviewUsecase struct {
	repo ReviewRepo
	log  *log.Helper
}

// NewReviewUsecase new a ReviewUsecase
func NewReviewUsecase(repo ReviewRepo, logger log.Logger) *ReviewUsecase {
	return &ReviewUsecase{repo: repo, log: log.NewHelper(logger)}
}

// CreateReview creates a Review, and returns the new Review.
func (uc *ReviewUsecase) CreateReview(ctx context.Context, r *model.ReviewInfo) (*model.ReviewInfo, error) {
	uc.log.WithContext(ctx).Debugf("CreateReview : %v", r)
	//1.数据校验
	//1.1参数基础校验 应该放在上一层（validate）
	//1.2参数业务校验 带业务逻辑的参数校验，比如已经评价过的订单不能再创建评价
	reviews, err := uc.repo.GetReviewByOrderID(ctx, r.OrderID)
	if err != nil {
		return nil, v1.ErrorDbFailed("查询数据库失败")
	}
	if len(reviews) > 0 {
		return nil, v1.ErrorOrderReviewed("订单号%d已评价", r.OrderID)
	}
	//2.生成id(雪花算法)  也可以接入公司内部分布式生成id的微服务
	r.ReviewID = snowflake.GenID()
	//3.查询订单和商品快照信息

	//4.入库
	return uc.repo.Save(ctx, r)
}

func (uc *ReviewUsecase) GetReview(ctx context.Context, reviewid int64) (*model.ReviewInfo, error) {
	uc.log.WithContext(ctx).Debugf("GetReview : %v", reviewid)
	review, err := uc.repo.FindByReviewID(ctx, reviewid)
	if err != nil {
		return nil, err
	}
	return review, nil
}

func (uc *ReviewUsecase) AuditReview(ctx context.Context, r *model.ReviewInfo) (*model.ReviewInfo, error) {
	uc.log.WithContext(ctx).Debugf("AuditReview : %v", r)
	review, err := uc.repo.AuditReview(ctx, r)
	if err != nil {
		return nil, err
	}
	return review, nil
}

func (uc *ReviewUsecase) CreateReply(ctx context.Context, r *ReplyParam) (*model.ReviewReplyInfo, error) {
	uc.log.WithContext(ctx).Debugf("CreateReply : %v", r)
	reply := &model.ReviewReplyInfo{
		ReplyID:   snowflake.GenID(),
		ReviewID:  r.ReviewID,
		StoreID:   r.StoreID,
		Content:   r.Content,
		PicInfo:   r.PicInfo,
		VideoInfo: r.VideoInfo,
	}
	return uc.repo.SaveReply(ctx, reply)
}

func (uc *ReviewUsecase) AppealReview(ctx context.Context, r *model.ReviewAppealInfo) (*model.ReviewAppealInfo, error) {
	uc.log.WithContext(ctx).Debugf("AppealReview : %v", r)
	r.AppealID = snowflake.GenID()
	return uc.repo.AppealReview(ctx, r)
}

func (uc *ReviewUsecase) AuditAppeal(ctx context.Context, r *model.ReviewAppealInfo) error {
	uc.log.WithContext(ctx).Debugf("AuditAppeal : %v", r)
	return uc.repo.AuditAppeal(ctx, r)
}

func (uc *ReviewUsecase) ListReviewByStoreID(ctx context.Context, storeid int64, page, size int32) ([]*MyReviewInfo, error) {
	uc.log.WithContext(ctx).Debugf("ListReviewByStoreID : %v", storeid)
	offset := (page - 1) * size
	limit := size
	return uc.repo.ListReviewByStoreID(ctx, storeid, offset, limit)
}

type MyReviewInfo struct {
	*model.ReviewInfo
	CreateAt     MyTime `json:"create_at"`
	UpdateAt     MyTime `json:"update_at"`
	Score        int32  `json:"score,string"`         // 评分
	ServiceScore int32  `json:"service_score,string"` // 商家服务评分
	ExpressScore int32  `json:"express_score,string"` // 物流评分
	HasMedia     int32  `json:"has_media,string"`     // 是否有图或视频
	OrderID      int64  `json:"order_id,string"`      // 订单id
	SkuID        int64  `json:"sku_id,string"`        // sku id
	SpuID        int64  `json:"spu_id,string"`        // spu id
	StoreID      int64  `json:"store_id,string"`      // 店铺id
	UserID       int64  `json:"user_id,string"`       // 用户id
	Anonymous    int32  `json:"anonymous,string"`
	ID           int64  `json:"id,string"`
	Version      int32  `json:"version,string"` // 乐观锁标记
	ReviewID     int64  `json:"review_id,string"`
	Status       int32  `json:"status,string"`     // 状态:10待审核；20审核通过；30审核不通过；40隐藏
	IsDefault    int32  `json:"is_default,string"` // 是否默认评价
	HasReply     int32  `json:"has_reply,string"`
}
type MyTime time.Time

func (t *MyTime) UnmarshalJSON(data []byte) error {
	s := strings.Trim(string(data), `"`)
	tmp, err := time.Parse(time.DateTime, s)
	if err != nil {
		return err
	}
	*t = MyTime(tmp)
	return nil
}
